<template>
  <div>
    <!-- 面包屑导航区 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片视图区 -->
    <el-card>
      <!-- 搜索与添加区域 -->
      <el-row :gutter="20">
        <el-col :span="7">
          <el-input placeholder="请输入内容" v-model="queryInfo.query" clearable @clear="getUserList">
        <el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
      </el-input>
        </el-col>
        <el-col :span="4">
          <el-button type="primary" @click="addDialogVisible=true">添加用户</el-button>
        </el-col>
      </el-row>
      <!-- 用户列表区 -->
      <el-table :data="userList" border stripe>
        <el-table-column type="index"></el-table-column>
        <el-table-column label="姓名" prop="username"></el-table-column>
        <el-table-column label="邮箱" prop="email"></el-table-column>
        <el-table-column label="电话" prop="mobile"></el-table-column>
        <el-table-column label="角色" prop="role_name"></el-table-column>
        <el-table-column label="状态" prop="mg_state">
          <template slot-scope="scope"><!-- {{scope.row}} 获取当前行数据-->
          <el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)">
          </el-switch>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180px">
          <template slot-scope="scope">
            <!-- 修改按钮 -->
            <el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row.id)"></el-button>
            <!-- 删除按钮 -->
            <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeUserById(scope.row.id)"></el-button>
            <!-- 分配角色按钮 -->
            <el-tooltip  effect="dark" content="分配角色" placement="top" :enterable="false">
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="setRole(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页区域 -->
       <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="queryInfo.pagenum"
      :page-sizes="[1, 2, 5, 10]"
      :page-size="queryInfo.pagesize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total">
    </el-pagination>
    </el-card>
    <!-- 添加用户对话框 -->
        <el-dialog
      title="添加用户"
      :visible.sync="addDialogVisible"
      width="50%"
      @close="addDialogClosed">
      <!-- 内容主题区域 -->
      <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="70px">
          <el-form-item label="用户名" prop="username">
            <el-input v-model="addForm.username" disabled></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input v-model="addForm.password"></el-input>
          </el-form-item>
          <el-form-item label="邮箱" prop="email">
            <el-input v-model="addForm.email"></el-input>
          </el-form-item>
          <el-form-item label="手机" prop="mobile">
            <el-input v-model="addForm.mobile"></el-input>
          </el-form-item>
      </el-form>
      <!-- 底部区 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addUser">确 定</el-button>
      </span>
    </el-dialog>
    <!--修改用户对话框  -->
    <el-dialog
      title="修改用户"
      :visible.sync="editDialogVisible"
      width="50%"
      @close = "editDialogClosed">
      <el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="70px">
        <el-form-item label="用户名">
          <el-input v-model="editForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email" >
          <el-input v-model="editForm.email"></el-input>
        </el-form-item>
        <el-form-item label="手机" prop="mobile">
          <el-input v-model="editForm.mobile" ></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editUserInfo">确 定</el-button>
      </span>
</el-dialog>
<!-- 分配角色对话框 -->
<el-dialog
  title="分配角色"
  :visible.sync="setRoleDialogVisible"
  width="50%"
  @close="setRoleDialogClosed">
 <div>
   <p>当前用户 : {{userInfo.username}}</p>
   <p>当前角色 : {{userInfo.role_name}}</p>
   <p>分配新角色:
     <el-select v-model="selectedRoleId" placeholder="请选择">
    <el-option
      v-for="item in rolesList"
      :key="item.id"
      :label="item.roleName"
      :value="item.id">
    </el-option>
  </el-select>
   </p>
 </div>
  <span slot="footer" class="dialog-footer">
    <el-button @click="setRoleDialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="saveRoleInfo">确 定</el-button>
  </span>
</el-dialog>
  </div>
</template>
<script>
/* 19.3 面包屑导航区、card区域 分别导入对应组件 点击首页跳转到home页 */
// 19.4 在全局(global.css)定义面包屑与card之间距离及字体
/* 设置card阴影(注：默认情况下卡片自身的样式权重比较高，需要加上!important才可以生效) */
// 19.5 搜索框区域 el-input  用栅格el-row行 el-col列 :span宽  :gutter间隔  按需导入组件
// 19.6 获取用户列表(table表格数据渲染)   后端接口请求：get,三个参数：query(查阅参数)、pagenum(当前页码)、pagesize(每页条数)
// 19.6.1 created中发起当前组件的首屏数据请求  this.getUserList()  在methods中定义this.getUserList()函数
// 19.6.2  get参数建议定义在data中为私有数据， this.$http.get('users', { params: this.queryInfo })
// 这样在页面创建期间会调用 this.getUserList()函数，发起ajax数据请求，
// 19.6.3 分析 ： elementui table表格，data为数据源(对象数组)，数组中的每一个对象被渲染为每一行，
// 在表格中嵌套很多模板列，每一列为el-table-column，label、width、prop分别为这一列标题、宽度、要渲染的数据项
// prop="data"表示这一列要渲染日期；
// 19.6.4.1按需导入Vue.use(table-column)等组件，全局注册
// 19.6.4.2 为表格指定数据源:data="userList"、
//           指定每一列：添加label标题，prop指定要填入的值(后端获取数据对应值的k)
//           如姓名对应username: "linken"  邮箱对应email: "asdf@qq.com"将k值username、email依次填入prop中，即可渲染出对应的数据
// 19.6.4.3  状态一列对应的是Boolean值，需要将Boolean值渲染为一个开关效果，为true,开关打开，为false，开关关闭;
//            如何把Boolean值按需渲染为一个开关哪？？？需要用到作用域插槽，拿到这一行的数据就可以通过.mg_state获取值进行渲染
//            1.加template模板，加属性slot-scope="scope"接收当前作用域数据，通过scope.row可以获取当前行数据
//            2.加el-switch组件,v-model可以绑定一个Boolean值控制开关的开与关，因此v-model可以绑定后端获取的mg_state值
//            操作一列不对应data数据源中的数据，因此可不要prop,只留下label,操作这一列必须要拿到对应的id才可以操作
//           (比如删除、修改用户等必须要拿到对应的id才可以进行，因此必须也只能用作用域插槽来进行操作)
//           1. 1.加template模板，加属性slot-scope="scope"接收当前作用域数据，通过scope.row可以获取当前行数据,scope.row.id获取当前列的id
//           2.添加button组件按钮  设置type:颜色  size:尺寸  icon:图标  一列中三个图标放不下，设置操作列width
//           3.鼠标放在最后一个按钮式提示按钮功能: tooltip组件 enterable：鼠标在tooltip框上时显示文字,离开时自动隐藏(设置为false时就可以，为true时文字一直显示)  placement：展示位置；effect：提供主题的颜色；content：内容文字；
// 19.6.4.4  美化表格   添加边框线border  隔行变色stripe  设置表格与上边的搜索框有一定距离：全局设置el-table：magin-top  设置字体
// 19.6.4.5    为表格添加索引列（第一列 ）  type="index"
// 20 分页区域    @size-change:只要切换每页显示多少条就会触发@size-change事件,在这个事件处理中可以拿到最新的每页显示条目pageSize,下边对应newSize;
//                @current-change:只要页码切换就会触发@current-change事件,在这个事件处理中可以拿到最新的页码值,下边对应newPage
//                :current-page：属性绑定,当前显示第几页的数据，动态绑定，可以根据data中的queryInfo的pagenum,:current-page="queryInfo.pagenum"
//                :page-sizes:数组，供page-size切换
//                :page-sizes：当前情况下每页显示多少条数据,动态绑定,可以根据data中的queryInfo的pagesize,:page-size="queryInfo.pagesize"
//                layout：字符串，指定页面上要显示的功能组件
//                 :total:总共有多少条数据，当前所有数据源都在data的total中绑定，动态绑定
// 20.1  点击改变pagesize，打印出当前最新的newSize，将最新获取到的newSize保存在当前data中，
// 因为newSize发生变化，即需要根据最新的newSize重新发起数据请求，获取这一页的数据this.getUserList()
// 20.2  点击改变页码值，打印出新的页码值newPage，需要将当前的newPage保存在data中，
// 因为newPage发生变化，即需要根据最新的newPage重新发起数据请求，获取这一页的数据this.getUserList()
// 20.3 在global.css中设置分页与table间距
// 21.实现用户状态修改(比如将第二条数据状态按钮打开，重新刷新页面发现按钮依旧为关，即状态没有被保存下来，只是在前台设置为打开，没有将状态修改同步到数据库中)
// 21.1  监听到switch开关状态的改变，拿到最新的状态值
// 21.1.1如何监听到开关状态改变？？ 绑定change事件，@change="userStateChanged()"只要调用这个函数就可以把当前行用户信息传到后端，
// 当前switch是用v-model="scope.row.mg_state"双向绑定，只要前边状态改变了，就可以通过v-model获取到最新状态值,因此直接将scope.row这一行数据传到@change中 @change="userStateChanged(scope.row)"
// 21.2   调用对应的api接口，把最新的状态保存在数据库中即可
// 22 实现搜索功能(输入名称点击按钮搜索用户)
//  22.1 将文本框和data数据双向绑定    v-model="queryInfo.query"搜索关键字
// 22.2 点击按钮调用获取用户列表的函数进行数据查询
// 22.2.1 给搜索按钮绑定单击事件,点击按钮，根据关键字实现搜索，发起查询用户请求@click="getUserList"
// 同时实现点击清空clearable，文本框重置，同时所有用户又被立即查询clear事件  @clear="getUserList"
// 23. 实现添加用户弹框功能
// 23.1   :visible.sync="addDialogVisible"是属性绑定，控制对话框的显示隐藏需要绑定在Boolean值上
// 点击'取消'和'确定'都会隐藏对话框，因此'取消'和'确定'绑定的点击事件是将:visible.sync的属性绑定值变为false，关闭对话框
// 23.2 为'添加用户'按钮添加点击事件，在点击事件中将addDialogVisible重置为true(弹框打开)
// 23.3 添加用户对话框中的表单    :model="addForm" :rules="addFormRules" ref="addFormRef" 不详细说了，和之前一样
// 23.4 实现自定义校验规则(eleui)(邮箱 手机号)
// 23.4.1 data中定义一个箭头函数代表一个校验规则,并用一个变量接收;
// 23.4.2  在具体规则中通过validator使用自定义校验规则
// 注:   data数据中定义变量，变量等于箭头函数即自定义校验规则,形参(rule, value, callback)
// rule:验证规则  value：需要验证的值  callback:回调函数  验证通过后直接调用callback函数，表示通过,通过后对话框表单变成绿色
// 调用callback()同时提供error对象表示验证失败了  callback(new Error('错误提示消息'))
// 在校验期间,一般是先定义正则表达式,在test(value)检验值是否是合法的,有了校验规则,需要再通过validator指定具体校验规则,
// 如age:[{ validator: checkAge, trigger: 'blur' }]age校验规则,校验项validator指向checkAge(自定义规则), trigger: 'blur'指定校验时机
// 23.5 添加用户对话框中的表单的重置 (每次点击添加用户都是初始状态,即输入框都是清空状态)即对话框关闭后重置表单就行
// 23.5.1 监听对话框关闭事件 对话框关闭时触发@close事件   @close="addDialogClosed"
// 23.5.2 在@close关闭事件中重置表单   this.$refs.addFormRef.resetFields()重置表单
// 23.6  添加用户的预验证功能(点击'确定'按钮后，不应该直接关闭弹窗，而是再点击确定按钮时调用一个函数，在函数中对表单进行预验证)
// 23.6.1  给'确定'按钮绑定一个事件处理函数   删掉@click="addDialogVisible = false"
// 24 修改用户操作(弹窗)
// 24.1 给'修改'按钮添加一个点击事件@click="showEditDialog(),加对话框，并在点击事件中打开对话框this.editDialogVisible = true
// 24.2根据id查询用户信息(点击'修改'按钮除了弹出对话框，还将用户之前的信息填充在对应框中)
// 24.2.1 拿到用户id：先在调方法时(作用域插槽,@click="showEditDialog(scope.row.id)")通过scope.row.id将用户id传到函数中，
// 接收到id后调用对应接口查询信息，并将获取成功的信息保存在editForm上  this.editForm = res.data
// 24.3 绘制修改用户的表单(用户名禁用不需要编辑和验证，邮箱和手机正常)
// 24.3.1  粘贴相关表单验证代码,:model="editForm" :rules="editFormRules" ref="editFormRef"
// 24.3.2 创建用户名、邮箱和手机三个item项，其中用户名不需要提供校验规则没有指定prop,每一项都要绑定在editForm上，这样才可以上述保存上去
// 最后在data中定义验证规则
// 24.3.3 修改表单关闭之后的重置操作(对话框关闭之后重新打开是重置之后的数据而不是上次未操作完的数据)
// 监听对话框给他绑定一个close事件 @close = "editDialogClosed"，每次关闭之后都重置 this.$refs.editFormRef.resetFields()
// 24.4提交修改之前表单预验证操作(点击确定按钮，先对用户表单进行预验证，预验证通过后才可以请求接口进行真正的修改)
// 24.4.1 删除@click="editDialogVisible = false"，给确定按钮添加预验证处理函数，valid为false直接return，为true发起请求
// 24.4.2验证通过后，发起put请求，携带参数提交到服务器，在判断状态码200，修改失败提示失败消息，修改成功  需要隐藏对话框，重新获取列表更新一下数据(因为用户信息更新成功要重新获取)最后提示用户更新成功
// 25  实现删除用户操作
// 25.1  点击'删除'按钮先提示用户是否继续删除，点击'取消'提示"已取消删除"，点击确定才会真正的将用户信息删除
// 25.2  按需导入导入MessageBox，通过原型挂载将MessageBox.confirm这个函数挂载到vue的原型对象上，名字为$confirm,这样在每一个组件中都可以通过
// this.$confirm来弹出一个确认消息的提示框，在提示框中通过.catch捕获用户的取消行为，不论用户取消/确认都可以用async、await简化promise操作，
// 通过confirmResult接收用户操作结果，用confirmResult进行if/else判断，如果confirmResult不等于字符串'confirm'证明用户取消删除，return出去提示取消， 如果等于,证明用户想要删除
// 25.3 用户点击'确定'想要删除，就应该发起请求来删除用户对应数据
// 26 提交用户列表功能代码
// 26.1 git status   在master分支上
// 26.2  git checkout -b user   (git checkout切换分支 -b新建分支   切换到新建user分支上)
// git branch
// git status
// git add .    添加到暂存区
// git commit -m "完成用户列表功能开发"    提交到本地user子分支仓库中
// git branch
// git push -u orign user   把本地user分支推送到云端origin仓库中同时以user分支保存
// git checkout master     切换到master分支
// git merge user 将user分支代码合并到master上(此时本地master代码是最新的但是云端仓库中master还是旧的)
// git push   将本地master分支代码推送到云端保存
// 27  权限列表开发
// 27.1   git创建权限列表分支
// git branch    处于master分支
// git checkout -b rights    从master分支上创建一个子分支rights并切换到子分支rights
// git branch     处于rights分支
// git push -u orign rights   将本地rights分支推送至云端分支rights(现在云端没有rights分支)
// 接下来所有的功能都在rights分支开发
// 34 用户-分配角色(点击分配角色,弹出对话框)
// 34.1 添加点击事件@click="setRole",设置在弹出对话框时加载出当前用户的基本信息,可以设置在点击按钮时,直接将这一行的信息scope.row传过来即可
// @click="setRole(scope.row)",用userInfo接收下,并保存在data中,接着在弹窗中直接使用userInfo.userName等获取用户信息
// 34.2 下拉下单:供用户选择新的分配角色;
// 点击分配角色按钮时,除了弹出对话框,还要获取所有角色列表,向后端接口请求数据,判断等于200时,用roleList接收一下所有角色列表数据,并在data中定义rolesList
// select选择器:v-model将用户选中的值双向同步到data中,下拉的每一个选项都需要for循环生成,每一个for循环中,label指定你看的文本,value指定选中这项之后真正选中的value值,
// /如你选中主管,真正记录在v-model中的:value是id,接着点击“确定”按钮，将分配的新角色保存在当前用户信息中
// 为确定按钮绑定事件处理函数，@click="saveRoleInfo"，触发这个函数时，我们应该先判断有没有选择一个新角色，if()取反，为true时，表示没有选择新角色，消息提示；没有return表示用户选择了新角色，发起请求保存用户的操作，
// 请求接口更新角色成功后需要重新刷新列表，再将弹窗关闭，
// 但有一个问题，更新成功后，再打开弹窗，没有重置选择项，隐藏因此给对话框添加一个监听对话框事件，弹窗关闭，置空选中角色
export default {
  data() {
    // 验证邮箱规则
    var checkEmail = (rule, value, callback) => {
      // 验证邮箱正则
      const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/
      if (regEmail.test(value)) {
        // 合法邮箱(校验值通过)
        return callback()
      }
      // 非法邮箱
      callback(new Error('请输入合法邮箱'))
    }
    // 验证手机号规则
    var checkMobile = (rule, value, callback) => {
      // const regMobile = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/
      const regMobile = /^[\u4e00-\u9fa5]{1,5}$/
      if (regMobile.test(value)) {
        // 合法手机号
        return callback()
      }
      callback(new Error('请输入合法手机号'))
    }
    return {
      // 获取用户列表的参数对象(params)，建议将get参数定义在data的私有数据中
      queryInfo: {
        query: '', /* 查询参数 搜索关键字 */
        pagenum: 1, /* 当前页数,默认请求第一页数据 */
        pagesize: 2 /* 当前每页显示多少条数据  默认每页显示2条数据 */
      },
      userList: [], /* 将后端获取到的"用户列表"数据保存在data中 */
      total: 0,
      // 控制对话框的显示与隐藏
      addDialogVisible: false,
      // 添加用户的表单数据
      addForm: {
        username: '',
        password: '',
        email: '',
        mobile: ''
      },
      // 添加表单的验证规则对象
      addFormRules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' },
          { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 15, message: '长度在 6 到 15 个字符', trigger: 'blur' }
        ],
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { validator: checkMobile, trigger: 'blur' }
        ]
      },
      // 控制修改用户对话框的显示与隐藏
      editDialogVisible: false,
      // 查询到的用户信息对象
      editForm: {},
      // 修改表单的验证规则对象
      editFormRules: {
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { validator: checkMobile, trigger: 'blur' }
        ]
      },
      // 控制分配角色对话框的显示与隐藏
      setRoleDialogVisible: false,
      // 需要被分配角色的用户信息
      userInfo: {},
      // 所有角色数据列表
      rolesList: [],
      // 已选中角色的id
      selectedRoleId: ''
    }
  },
  created() {
    this.getUserList()
  },
  methods: {
    // get请求   get参数params有三个属性  推荐将get参数定义在data的私有数据中,直接用this.queryInfo替代
    async getUserList() {
    // 这样在页面创建期间会调用 this.getUserList()函数，发起ajax数据请求，接下来get函数会返回一个promise对象，
    // 为了简化promise对象，用async和await优化异步操作，接着会得到一个数据对象，从数据对象身上解构赋值出来一个data属性，重命令为res
    // 打印res,获取mes:获取管理员列表成功 status:200  data中total:4,users：array(2)
    // 数据拿到后，首先判断状态码是否等于200，!=200，失败
    // 等于200时，表示数据获取成功，首先将后端获取数据userList、total保存在data中，接着赋值，
      const { data: res } = await this.$http.get('users', { params: this.queryInfo })
      // console.log(res, '22222') /* 此处bug：没有在users页面刷新导致没有数据打印 */
      if (res.meta.status !== 200) return this.$message.error('获取用户列表失败')
      //  赋值
      this.userList = res.data.users
      this.total = res.data.total
    },
    // 监听pagesize改变事件  点击改变pagesize，打印出当前最新的newSize，将最新获取到的newSize保存在当前data中
    // 因为newSize发生变化，即需要根据最新的newSize重新发起数据请求，获取这一页的数据this.getUserList()
    handleSizeChange(newSize) {
      // console.log(newSize)
      this.queryInfo.pagesize = newSize
      this.getUserList()
    },
    // 监听页码值改变事件  点击改变页码值，打印出当前最新的页码值newPage，将最新获取到的newPage保存在当前data中
    // 因为newPage发生变化，即需要根据最新的newPage重新发起数据请求，获取这一页的数据this.getUserList()
    handleCurrentChange(newPage) {
      // console.log(newPage)
      this.queryInfo.pagenum = newPage
      this.getUserList()
    },
    // 监听switch开关状态的改变 ,
    // 打印userinfo,获取当前行用户信息，点击开关打开，立即获取最新用户信息,状态为true,点击开关关闭，立即获取最新用户信息,状态为false
    //  api接口  put请求  接口url：users/:uid/state/:type(注:以':'开头的都是参数,其中uid和type是动态参数,为了拼接动态参数，需要将url的单引号''用模板字符串``反引号来代替)
    // 拿到最新状态值后调用api接口保存状态：请求接口,数据拿到后进行赋值，首先判断状态码是否等于200，!=200，失败,此时前台状态已改,但是后端数据库未改(如前台为开true，但是请求失败，后端数据为false)
    // 但是页面状态已改为true,因此需要重置回去(直接取反即可),需要userinfo.mg_state = !userinfo.mg_state，因此操作失败，提示用户更新用户状态失败，同时取反保证页面状态不变；操作成功，提示用户更新用户状态成功；
    async userStateChanged(userinfo) {
      // console.log(userinfo, '0000')
      const { data: res } = await this.$http.put(`users/${userinfo.id}/state/${userinfo.mg_state}`)
      if (res.meta.status !== 200) {
        userinfo.mg_state = !userinfo.mg_state
        return this.$message.error('更新用户状态失败')
      }
      this.$message.success('更新用户状态成功')
    },
    // 监听添加用户对话框的关闭事件   重置表单
    addDialogClosed() {
      this.$refs.addFormRef.resetFields()
    },
    // 点击'确定'按钮添加新用户
    // 点击确定，validate对表单预验证，如果validate校验失败时(valid为false)直接return，不走添加逻辑；
    // 如果没有被return出去，表示表单预校验通过，可以发起添加用户的网络请求
    // 请求路径：users  请求方法：post  请求参数:username password email mobile(data中addForm包含这四个参数字段，直接this.addForm)
    //  添加用户失败提示消息，反之成功提示消息后需要将对话框关闭，同时要刷新下用户列表 this.getUserList()(因为用户有新增)
    addUser() {
      this.$refs.addFormRef.validate(async valid => {
        console.log(valid) // true/false
        // eslint-disable-next-line no-useless-return
        if (!valid) return
        // 可以发起添加用户的网络请求
        const { data: res } = await this.$http.post('users', this.addForm)
        if (res.meta.status !== 201) {
          this.$message.error('添加用户失败')
        }
        this.$message.success('添加用户成功')
        // 隐藏添加用户的对话框
        this.addDialogVisible = false
        this.getUserList()
      })
    },
    // 展示用户编辑的对话框  请求路径：users/:id  请求方法：get
    // 将:id删掉，因为是动态数据，要用字符串拼接+id('users/' + id)
    // 数据获取成功后将查询到的数据保存在data上供页面使用editForm: {}
    async showEditDialog(id) {
      // console.log(id, 'id')
      const { data: res } = await this.$http.get('users/' + id)
      if (res.meta.status !== 200) {
        return this.$message.error('查询用户信息失败')
      }
      this.editForm = res.data
      this.editDialogVisible = true
    },
    // 监听修改用户对话框的关闭事件
    editDialogClosed() {
      this.$refs.editFormRef.resetFields()
    },
    // 修改用户信息并提交
    // 只有预校验通过了才可以发起请求，否则直接return
    editUserInfo() {
      this.$refs.editFormRef.validate(async valid => {
        console.log(valid)
        // 预校验不通过直接return出去，通过了就发起请求
        if (!valid) return
        // 发起修改用户信息的数据请求  请求路径：users/:id   请求方法：put
        const { data: res } = await this.$http.put('users/' + this.editForm.id, {
          email: this.editForm.email,
          mobile: this.editForm.mobile })
        if (res.meta.status !== 200) {
          return this.$message.error('更新用户信息失败')
        }
        // 如果更新成功了，需要隐藏对话框，重新获取列表更新一下数据(因为用户信息更新成功要重新获取)最后提示用户更新成功
        // 关闭对话框
        this.editDialogVisible = false
        // 刷新数据列表
        this.getUserList()
        // 提示修改成功
        this.$message.success('更新用户信息成功')
      })
    },
    // 根据id删除对应用户信息
    // 点击删除弹窗提示是否删除数据
    async removeUserById(id) {
      // console.log(id, '111')点击删除打印对应id
      const confirmResult = await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(error => error)
      // 如果用户确认删除，返回字符串'confirm'
      //  如果用户取消删除，返回字符串'cancel'
      if (confirmResult !== 'confirm') {
        return this.$message.info('已取消删除')
      }
      console.log('确认删除')
      // 删除用户接口   请求路径：users/:id  请求方法：delete
      // id是动态的，用字符串拼接具体要删除的id，删除成功后服务器返回promise,用await/async简化操作(async此时removeUserById已有)
      // if判断200，删除失败，提示错误消息，删除成功，提示删除成功且此时需要刷新一下用户列表this.getUserList()
      const { data: res } = await this.$http.delete('users/' + id)
      if (res.meta.status !== 200) {
        return this.$message.error('删除用户失败')
      }
      this.$message.success('删除用户成功')
      this.getUserList()
    },
    // 展示分配角色的对话框
    async setRole(userInfo) {
      this.userInfo = userInfo
      // 在展示对话框之前,获取所有角色列表,请求接口获取数据,get,roles
      const { data: res } = await this.$http.get('roles')
      if (res.meta.status !== 200) { return this.$message.error('获取角色列表失败') }
      this.rolesList = res.data
      this.setRoleDialogVisible = true
    },
    // 点击按钮，分配角色
    async saveRoleInfo() {
      if (!this.selectedRoleId) {
        return this.$message.error('请选择要分配的角色')
        // 请求路径：users/:id/role  请求方法：put
      }
      const { data: res } = await this.$http.put(`users/${this.userInfo.id}/role`, { rid: this.selectedRoleId })
      if (res.meta.status !== 200) {
        return this.$message.error('更新角色失败')
      }
      this.$message.success('更新角色成功')
      this.getUserList()
      this.setRoleDialogVisible = false
    },
    // 监听分配角色对话框的关闭事件
    setRoleDialogClosed() {
      this.selectedRoleId = ''
      // ？？？？
      this.userInfo = {}
    }
  }
}
</script>

<style lang="less" scoped></style>
